`timescale 1ns / 1ps
/******************************************************************************
*                                                                             *
* UTICA softcore v0.1                                                         *
*                                                                             *
* Copyright (c) 2012 Andrew D. Zonenberg                                      *
* All rights reserved.                                                        *
*                                                                             *
* Redistribution and use in source and binary forms, with or without modifi-  *
* cation, are permitted provided that the following conditions are met:       *
*                                                                             *
*    * Redistributions of source code must retain the above copyright notice  *
*      this list of conditions and the following disclaimer.                  *
*                                                                             *
*    * Redistributions in binary form must reproduce the above copyright      *
*      notice, this list of conditions and the following disclaimer in the    *
*      documentation and/or other materials provided with the distribution.   *
*                                                                             *
*    * Neither the name of the author nor the names of any contributors may be*
*      used to endorse or promote products derived from this software without *
*      specific prior written permission.                                     *
*                                                                             *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF        *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN     *
* NO EVENT SHALL THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT,         *
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT    *
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,   *
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY       *
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT         *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF    *
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.           *
*                                                                             *
******************************************************************************/

/**
	@file UticaCPUPipelineForwarding.v
	@author Andrew D. Zonenberg
	@brief Pipeline forwarding for a single register
 */
module UticaCPUPipelineForwarding(
	dstreg,
	rawval,
	mem_regwrite, mem_rdid, mem_rdval, mem_memop, mem_mfhi, mem_mflo,
	writeback_regwrite, writeback_rdid, writeback_rdval, writeback_memread,
	writeback_mfhi, writeback_mflo,
	forwarded, stall_for_mem
    );

	////////////////////////////////////////////////////////////////////////////////////////////////
	// IO declarations
	
	input wire[4:0] dstreg;
	
	input wire[31:0] rawval;							//Original value straight from register file
	
	input wire mem_regwrite;							//Data needed to forward from mem stage
	input wire[4:0] mem_rdid;
	input wire[31:0] mem_rdval;
	input wire mem_memop;
	
	input wire mem_mfhi;
	input wire mem_mflo;
	
	input wire writeback_regwrite;					//Data needed to forward from writeback stage
	input wire[4:0] writeback_rdid;
	input wire[31:0] writeback_rdval;
	input wire writeback_memread;						//if asserted writeback is coming from a memory read and not available yet!
	
	input wire writeback_mfhi;
	input wire writeback_mflo;
	
	output reg[31:0] forwarded = 0;					//Output
	output reg stall_for_mem = 0;						//if asserted, cannot forward
	
	////////////////////////////////////////////////////////////////////////////////////////////////
	// Forwarding logic
	
	always @(dstreg,
				rawval,
				mem_regwrite, mem_rdid, mem_rdval, mem_memop, mem_mfhi, mem_mflo,
				writeback_regwrite, writeback_rdid, writeback_rdval, writeback_memread,
				writeback_mfhi, writeback_mflo
				) begin
				
		stall_for_mem <= 0;
		forwarded <= 0;
				
		//Mem stage contains valid data
		//and is being written to this register
		if(mem_regwrite && (mem_rdid == dstreg)) begin
		
			if(mem_memop || mem_mfhi || mem_mflo)
				stall_for_mem <= 1;
			
			else		
				forwarded <= mem_rdval;
		end
		
		//Writeback stage contains valid data
		//and is being written to this register
		else if(writeback_regwrite && (writeback_rdid == dstreg)) begin
			if(writeback_memread || writeback_mfhi || writeback_mflo)
				stall_for_mem <= 1;
			else
				forwarded <= writeback_rdval;
		end
		
		//No forwarding necessary
		else begin
			forwarded <= rawval;
		end
		
	end

endmodule
